#!/bin/bash

set -e
# This will fail on gcc6
# See https://www.cfd-online.com/Forums/openfoam-installation/180040-openfoam-2-4-0-error-building-paraview-4-1-0-a.html#post627619

VERSION=2.4.0
BASEDIR=$PWD
ROOTFS=$BASEDIR/ROOTFS
SRCDIR=$BASEDIR/OpenFOAM-$VERSION

# enable parallel build
export MAKEFLAGS="-j `nproc`"
export WM_NCOMPPROCS="`nproc`"

# Check whether we need to download the tarbalj0j0
if [ ! -f OpenFOAM-$VERSION.tgz ]; then
    wget http://downloads.sourceforge.net/foam/OpenFOAM-$VERSION.tgz
fi

# Extract the target version
if [ ! -d OpenFOAM-$VERSION ]
then
    tar zxf OpenFOAM-$VERSION.tgz

    ## Patch bashrc to request debug compilation.
    #cd $SRCDIR
    #patch -p1 < $BASEDIR/patches/debug.patch

    # OpenFOAM should not call exit() - in OSv exit shutdowns whole VM
    cd $SRCDIR
    patch -p1 < $BASEDIR/patches/exit.patch

    # Patch the solidMixtureProperties library
    cd $SRCDIR
    patch -p1 < $BASEDIR/patches/solidMixtureProperties-dependency.patch
    # Patch missing dependency - libfluidThermophysicalModels.so uses libspecie.so
    patch -p1 < $BASEDIR/patches/thermophysicalModels-dependency.patch
    # required when compiling on host with flex 2.6
    patch -p1 < $BASEDIR/patches/readSTLASCII-and-flex-2.6-fix.patch
fi
cd $BASEDIR

# Set OpenFOAM's environment variables required to build the package. You should change this to cshrc if
# that's the shell you are using.
export FOAM_INST_DIR=$BASEDIR
. $SRCDIR/etc/bashrc

# First, compile the wmake used to build OpenFOAM sources.
cd $SRCDIR/wmake/src
make

# Make the OpenFOAM library
cd $SRCDIR/src
./Allwmake

# Which solvers will be included into image
APPDIRS=""
APPDIRS+=" applications/solvers/basic/potentialFoam"
APPDIRS+=" applications/solvers/incompressible/simpleFoam"
APPDIRS+=" applications/solvers/compressible/rhoSimpleFoam"
APPDIRS+=" applications/solvers/incompressible/simpleFoam/porousSimpleFoam"
APPDIRS+=" applications/solvers/compressible/rhoSimpleFoam/rhoPorousSimpleFoam"
APPDIRS+=" applications/solvers/incompressible/pisoFoam"
APPDIRS+=" applications/solvers/incompressible/pimpleFoam"
APPDIRS+=" applications/utilities/parallelProcessing/decomposePar"
APPDIRS+=" applications/utilities/parallelProcessing/reconstructPar"

cd $BASEDIR
set -o nounset
rm -fr "$ROOTFS"
set +o nounset
mkdir -p $ROOTFS/usr/lib
mkdir -p $ROOTFS/usr/bin
mkdir -p $ROOTFS/openfoam

function relink_so () {
  APPDIR="$1"
  DESTF_SHORT=`basename "$APPDIR"`
  DESTF_FULL="$SRCDIR/platforms/$WM_OPTIONS/bin/$DESTF_SHORT"

  # Go and build application $DESTF_SHORT (say simpleFoam, potentialFoam etc).
  # First, build the regular Linux executable $DESTF_SHORT, capture its build command,
  # then re-build shared object $DESTF_SHORT.so.
  cd "$SRCDIR/$APPDIR"
  rm -f "$DESTF_FULL"
  # wmake will print used make command to stdout.
  # Capture it, then transform it to build shared object instead of executable.
  # When running VAR=`wmake`, some additional "make[1]: ..." header is added,
  # compared to entering only 'wmake' in shell.
  CAPTURED_CMD1=`wmake`

  # Remove 'make[1]' header
  # Change output file from ' -o $DESTF_SHORT' to ' -o $DESTF_SHORT.so'
  CAPTURED_CMD2=`echo "$CAPTURED_CMD1" | sed -e '/^make\[.*$/d' -e "s| -o $DESTF_FULL| -o $DESTF_FULL.so -shared|" `
  echo "/**********************************************************************/"
  echo "CAPTURED_CMD1"
  echo "$CAPTURED_CMD1"
  echo "/*********************************/"
  echo "CAPTURED_CMD2"
  echo "$CAPTURED_CMD2"
  echo "/*********************************/"
  # sign \ is problem for simple $CAPTURED_CMD2, so pipe command to bash
  echo "$CAPTURED_CMD2" | bash
  echo "/**********************************************************************/"
  file "$DESTF_FULL"*

  cp "$DESTF_FULL".so  $ROOTFS/usr/bin

  # System supplied openMPI libraries should not be used (mpi|mpi_cxx|open-pal|open-rte)
  # Simple programs work without libnl-3.so and libnl-route-3.so.
  # With them, complain about symbol tdestroy.
  # This seems to be part of glibc GNU extension, and is missing in OSv.
  ldd "$DESTF_FULL".so | grep -Po '(?<=> )/[^ ]+' | sort | uniq | grep -Pv 'lib(c|gcc|dl|m|util|rt|pthread|stdc\+\+|mpi|mpi_cxx|open-pal|open-rte|nl-3|nl-route-3).so' | xargs -I {} install  {} $ROOTFS/usr/lib
  cd -
}

for appdir in $APPDIRS
do
  relink_so "$appdir"
done

# Also install libfieldFunctionObjects.so as it is not linked from the simpleFoam
install $SRCDIR/platforms/$WM_OPTIONS/lib/libfieldFunctionObjects.so $ROOTFS/usr/lib
install $SRCDIR/platforms/$WM_OPTIONS/lib/libforces.so $ROOTFS/usr/lib

# Gdb has problem with files copied to ROOTFS.
# loader.py does find .so file in ROOTFS, but it doesn't know where are object files.
# Put path to original .so files (ffsrc) into usr.manifest, instead of
# path to copies in ROOTFS/ (ffdest).
echo "" > usr.manifest
FFSO=`find $ROOTFS -type f -iname '*\.so'`
for ffdest in $FFSO
do
    #echo '--------------------------------'
    #echo "DBG ffdest=$ffdest"
    ffbase=`basename $ffdest`
    ffsrc=`find $SRCDIR/platforms/ -type f -iname $ffbase`

    #echo "DBG ffsrc=$ffsrc"
    # We have platforms/linux64GccDPOpt/lib/dummy/libPstream.so and
    # platforms/linux64GccDPOpt/lib/openmpi-system/libPstream.so
    # Use the open-mpi one.
    ffsrc2=`echo "$ffsrc" | sed '/\/lib\/dummy\//d'`
    # But libmetisDecomp.so is only in dummy, so check for empth ffsrc2
    if [ ! -z "$ffsrc2" ]
    then
        ffsrc=$ffsrc2
    fi
    #echo "DBG ffsrc2=$ffsrc2"

    ffdest2=`echo $ffdest | sed "s|$ROOTFS||"`
    #echo "DBG ffdest2=$ffdest2"
    echo "$ffdest2: $ffsrc" >> usr.manifest
done

# Copy the configuration files and scripts to the image.
cp -r $SRCDIR/etc $ROOTFS/openfoam

echo "#
/openfoam/etc/**: $ROOTFS/openfoam/etc/**
#
/usr/bin/decomposePar: ->/usr/bin/decomposePar.so
/usr/bin/reconstructPar: ->/usr/bin/reconstructPar.so
" >> usr.manifest

# Tu run the openfoam on OSv you need to upload the case explicitly with
# ./scripts/upload-case.py script.
# The script creates new copy of the image and uploads the case. The advantage
# is that the image is built only once.
